/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package mopso;

import util.Sigmoid;

/**
 *
 * @author robson
 */
public class PSO {

    public double updateLinearInertia(double maxInertia, double minInertia, int currentIteration, int maxIteration) {
        double inertia;
        
        inertia = maxInertia - ((maxInertia - minInertia) * (  ((double)currentIteration)  / ((double) maxIteration)));
        
        if ( inertia < 0.0 ) {
            inertia = 0.0;
        }
        
        return inertia;        
    }
    
    public double updateRandomInertia() {
        return 0.5 + (Math.random() * 0.5);
    }    

    public Particle updatePosition(Particle particle, Problem problem, double inertia, double cognitionLearningRate, double socialLearningRate) {
        double[] velocities = particle.getParticleData().getVelocities().clone();
        double[] positions = particle.getParticleData().getPositions().clone();
        double r1;
        double r2;
        double pd;
        double gd;
        double minBound;
        double maxBound;

        for (int i = 0; i < problem.getNDimensions(); i++) {
            r1 = Math.random();
            r2 = Math.random();

            pd = particle.getLeaderPbest().getPositions()[i];
            gd = particle.getLeader().getParticleData().getPositions()[i];

            minBound = problem.getMinBound(i);
            maxBound = problem.getMaxBound(i);

            velocities[i] = (inertia * velocities[i]) +
                    (cognitionLearningRate * r1 * (pd - positions[i])) +
                    (socialLearningRate * r2 * (gd - positions[i]));

            if (Math.abs(velocities[i]) > (maxBound - minBound)) {
                velocities[i] = Math.signum(velocities[i]) * (maxBound - minBound);
            }

            /**Aplicação da sigmoide logistica na atualizacao da posição**/
            positions[i] = Sigmoid.sigmoid(velocities[i]);

            if (positions[i] < minBound) {
                positions[i] = minBound;
                velocities[i] *= -1;
            } else if (positions[i] > maxBound) {
                positions[i] = maxBound;
                velocities[i] *= -1;
            }
        }

        particle.getParticleData().setVelocities(velocities);
        particle.getParticleData().setPositions(positions);
        return particle;
    }
    
    public Particle_CSS updatePosition(Particle_CSS particle_CSS, Problem problem, double inertia, double cognitionLearningRate, double socialLearningRate) {
        double[] velocities = particle_CSS.getParticleData().getVelocities().clone();
        double[] positions = particle_CSS.getParticleData().getPositions().clone();
        double r1;
        double r2;
        double g1d;
        double g2d;
        double minBound;
        double maxBound;

        for (int i = 0; i < problem.getNDimensions(); i++) {
            r1 = Math.random();
            r2 = Math.random();

            g1d = particle_CSS.getGBest1().getParticleData().getPositions()[i];
            g2d = particle_CSS.getGBest2().getParticleData().getPositions()[i];            
            
            minBound = problem.getMinBound(i);
            maxBound = problem.getMaxBound(i);

            velocities[i] = (inertia * velocities[i]) +
                    (cognitionLearningRate * r1 * (g1d - positions[i])) +
                    (socialLearningRate * r2 * (g2d - positions[i]));

            if (Math.abs(velocities[i]) > (maxBound - minBound)) {
                velocities[i] = Math.signum(velocities[i]) * (maxBound - minBound);
            }

            positions[i] += velocities[i];

            if (positions[i] < minBound) {
                positions[i] = minBound;
                velocities[i] *= -1;
            } else if (positions[i] > maxBound) {
                positions[i] = maxBound;
                velocities[i] *= -1;
            }
        }

        particle_CSS.getParticleData().setVelocities(velocities);
        particle_CSS.getParticleData().setPositions(positions);
        return particle_CSS;
    }        
}
